package com.feng.filter;

import com.feng.entity.RestResponse;
import com.feng.utils.Const;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

//@Component
//@Order(Const.CURRENT_LIMIT_FILTER)
public class CurrentLimitFilter extends HttpFilter {

    final
    StringRedisTemplate redisTemplate;

    public CurrentLimitFilter(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilter(HttpServletRequest request, 
                            HttpServletResponse response, 
                            FilterChain chain) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        String ip = request.getRemoteAddr();
        if(tryCheck(ip)){
            chain.doFilter(request, response);
        }else{
            response.getWriter().write(RestResponse.failure(401, "当前IP访问过于频繁，请稍后再试").asJsonString());
        }
    }

    private boolean tryCheck(String ip){
        Boolean blackIp = redisTemplate.hasKey(Const.CURRENT_LIMIT_IP + ip);
        if(blackIp) return false;
        else{
            Boolean count = redisTemplate.hasKey(Const.CURRENT_LIMIT_COUNT + ip);
            if(count) {
                if(Integer.parseInt(redisTemplate.opsForValue().get(Const.CURRENT_LIMIT_COUNT + ip)) > 50){
                    redisTemplate.delete(Const.CURRENT_LIMIT_COUNT + ip);
                    redisTemplate.opsForValue().set(Const.CURRENT_LIMIT_IP + ip, "1", 30, TimeUnit.SECONDS);
                    return false;
                }
                redisTemplate.opsForValue().increment(Const.CURRENT_LIMIT_COUNT + ip);
            }else{
                redisTemplate.opsForValue().set(Const.CURRENT_LIMIT_COUNT + ip, "1", 1, TimeUnit.SECONDS);
            }
        }
        return true;
    }
}
